import React, {FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef} from "react";
import {useTranslation} from "react-i18next";
import useStateRef from "../customUse/useStateRef";
import {isString, tryFunction, tryFunctionAsync} from "../utils";
import {getFormView} from "../services/ViewService";
import Config from "../Config";
import {Button} from "antd";
import BaseForm from "../module/form/BaseForm.tsx";
import "./css/GlobalSearch.less";

interface GlobalSearchProps {
    menuId?: string,
    view: string,
    onSearch: Function,
    onReset: Function,
    dataSource?: any,
    initData?: any,
    init?: any,
    formItemLayout?: string,
    layout?: string,
    onValuesChange?: Function
    beforeSubmit?: Function
}

const GlobalSearch: FC<GlobalSearchProps> = (props) => {
    const {t} = useTranslation();
    const formRef: any = useRef();

    const viewRef = useRef([]);
    const linkageRef = useRef({});

    const [view, setView] = useStateRef([], viewRef);

    const loadView: Function = useCallback(async () => {
        let {view, initData = {}, dataSource = {}}: { view: any[] | string, initData: any, dataSource: any } = props;
        if (isString(view)) {
            let result: any = await getFormView(view, initData, dataSource);
            tryFunction(() => {
                eval("window.linkageForm =" + result.linkageControl)
                linkageRef.current = window.linkageForm || {};
            });
            if (result.form && linkageRef.current.beforeFormatView) {
                await tryFunctionAsync(async () => {
                    result.form = (await linkageRef.current.beforeFormatView.call(null, result.form, initData)) || [];
                })
            }
            setView(result.form);
        } else {
            setView(Array.from(view));
        }
    }, [props]);

    const init: Function = useCallback(() => {
        loadView();
    }, [props.view]);

    const beforeSubmit: Function = useCallback(async (params: any, view: any) => {
        if (props.beforeSubmit) {
            return props.beforeSubmit(params, view);
        } else if (linkageRef.current.beforeSubmit) {
            return await linkageRef.current.beforeSubmit.call(null, params, view);
        }
        return params;
    }, [props.beforeSubmit]);

    const onSubmit: Function = useCallback(async (params: any) => {
        let newParams = await beforeSubmit(params, view);
        props.onSearch && props.onSearch(newParams);
    }, [props.onSearch, view]);

    const handleReset: Function = useCallback(() => {
        formRef.current.resetFields();
        props.onReset && props.onReset();
    }, [props.onReset]);


    useImperativeHandle(props.init, () => {
        return formRef.current;
    });

    const onValuesChange: Function = useCallback(async (changedValues: any, allValues: any) => {
        await tryFunctionAsync(async () => {
            linkageRef.current.valueChangeFormatView && (await linkageRef.current.valueChangeFormatView.call(null, allValues, formRef.current.updateView));
        })
        props.onValuesChange && props.onValuesChange(changedValues, allValues, formRef.current.updateView);
    }, [props.onValuesChange]);

    useEffect(() => {
        init()
    }, [props.view]);

    const renderGlobalSearch = useMemo(() => {
        if (!view.length) {
            return null;
        }
        return (
            <div className={"sf_core_search_form"}>
                <BaseForm
                    init={formRef}
                    menuId={props.menuId}
                    formItemLayout={props.formItemLayout || Config.form.defaultEnItemLayout}
                    hideValid={true}
                    view={view}
                    layout={props.layout}
                    labelWidth={130}
                    isSearch={true}
                    onSubmit={onSubmit}
                    onValuesChange={onValuesChange}
                >
                    <div className={"sf_core_search_form_btn"}>
                        <div className="sf_core_search_form_btn_box">
                            <Button size={"small"}
                                    type="primary"
                                    htmlType="submit">{t("search")}</Button>
                            <Button size={"small"}
                                    style={{marginLeft: 5}}
                                    onClick={handleReset}>{t("resetting")}</Button>
                        </div>
                    </div>
                </BaseForm>
            </div>
        )
    }, [props.menuId, view]);

    return (renderGlobalSearch);
};

export default React.memo(GlobalSearch);